//
//  WmcPushTransition.swift
//  YPWatermarkCamera
//
//  Created by 赵新 on 2022/3/22.
//

import UIKit
import YPBedrock

public extension WmcTransition {
    enum Operation {
        case none, push, pop
//        case present, dismiss
    }

    enum Style {
        case top
        case left
        case bottom
        case right
        case alpha
    }
}

extension WmcTransition {
    /// 数值，用于处理出现和消失
    struct Numerical<T> {
        // Lifecycle

        /// 统一实例化
        init(all: T) {
            self.show = all
            self.hide = all
        }

        init(show: T, hide: T) {
            self.show = show
            self.hide = hide
        }

        // Internal

        var show: T
        var hide: T

        func value(_ operation: Operation) -> T {
            switch operation {
            case .push: return show
            case .pop: return hide
            default: return show
            }
        }
    }
}

// MARK: - [WmcTransition]

open class WmcTransition: NSObject {
    // Lifecycle

    init(operation: Operation, style: Style) {
        super.init()
        self.operation = operation
        self.style = style
    }

    // Internal

    /// 样式
    var operation: Operation = .none

    /// 动画样式
    var style: Style = .right

    /// 出现/消失时候的动画时间
    var animationDuration: Numerical<CGFloat> = .init(show: 0.6, hide: 0.4)

    /// 动画延时
    var delay: Numerical<CGFloat> = .init(all: 0)

    /// 弹性系数 0-1 越小弹性效果越明显
    var usingSpringWithDamping: Numerical<CGFloat> = .init(show: 0.8, hide: 2)

    /// 初始速度系数，0-100 越大初始速度越快
    var initialSpringVelocity: Numerical<CGFloat> = .init(show: 0.1, hide: 0)

    /// 动画曲线类型
    var animationOptions: Numerical<UIView.AnimationOptions> = .init(show: .curveEaseOut, hide: .curveLinear)
}

// MARK: - UIViewControllerAnimatedTransitioning

extension WmcTransition: UIViewControllerAnimatedTransitioning {
    // MARK: - 协议实现

    public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval {
        switch operation {
        case .push: return animationDuration.show
        case .pop: return animationDuration.hide
        default: return Wmc_animationDuration
        }
    }

    public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
        switch operation {
        case .push: showAnimation(transitionContext)
        case .pop: hideAnimation(transitionContext)
        default: break
        }
    }

    // MARK: - 动画实现

    // 出现转场
    open func showAnimation(_ transitionContext: UIViewControllerContextTransitioning) {
        guard let fromVC = transitionContext.viewController(forKey: .from),
              let toVC = transitionContext.viewController(forKey: .to) else { return }
        let containerView = transitionContext.containerView
        containerView.addSubview(fromVC.view)
        containerView.addSubview(toVC.view)

        var startToVCFrame = toVC.view.frame

        switch style {
        case .top:
            startToVCFrame = startToVCFrame.yp.set(y: -startToVCFrame.height)
        case .left:
            startToVCFrame = startToVCFrame.yp.set(x: -startToVCFrame.width)
        case .bottom:
            startToVCFrame = startToVCFrame.yp.set(y: startToVCFrame.height)
        case .right:
            startToVCFrame = startToVCFrame.yp.set(x: startToVCFrame.width)
        case .alpha:
            break
        }
        toVC.view.alpha = 0
        toVC.view.frame = startToVCFrame

        animation(operation) {
            toVC.view.alpha = 1
            toVC.view.frame = Wmc_screen
        } completion: {
            transitionContext.completeTransition(true)
        }
    }

    // 消失转场
    open func hideAnimation(_ transitionContext: UIViewControllerContextTransitioning) {
        guard let fromVC = transitionContext.viewController(forKey: .from),
              let toVC = transitionContext.viewController(forKey: .to) else { return }
        let containerView = transitionContext.containerView
        containerView.addSubview(toVC.view)
        containerView.addSubview(fromVC.view)
        var endToVCFrame = toVC.view.frame

        switch style {
        case .top:
            endToVCFrame = endToVCFrame.yp.set(y: -endToVCFrame.height)
        case .left:
            endToVCFrame = endToVCFrame.yp.set(x: -endToVCFrame.width)
        case .bottom:
            endToVCFrame = endToVCFrame.yp.set(y: endToVCFrame.height)
        case .right:
            endToVCFrame = endToVCFrame.yp.set(x: endToVCFrame.width)
        case .alpha:
            break
        }
        fromVC.view.alpha = 1

        animation(operation) {
            fromVC.view.alpha = 0
            fromVC.view.frame = endToVCFrame
        } completion: {
            transitionContext.completeTransition(true)
        }
    }

    /// 通用动画函数
    func animation(_ operation: Operation,
                   animateBlock: @escaping YPBlock.Empty,
                   completion: @escaping YPBlock.Empty)
    {
        UIView.animate(withDuration: animationDuration.value(operation),
                       delay: delay.value(operation),
                       usingSpringWithDamping: usingSpringWithDamping.value(operation),
                       initialSpringVelocity: initialSpringVelocity.value(operation),
                       options: animationOptions.value(operation)) {
            animateBlock()
        } completion: { _ in
            completion()
        }
    }
}
